package com.le.tester.imooc.oldfairy.coding.buffer;

import com.le.tester.javaThink.fourth.net.mindview.util.CountingGenerator;
import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * createTime：2023/5/12 14:10
 * description：使用buffer写入文件和读取文件
 * 文件读写三部曲--nio
 * 1.文件流的操作
 * 2.使用channel
 * 3.使用ByteBuffer
 */
public class BufferExample {

    private String filePath = "E:\\Desktop\\test.txt";


    @Test
    public void gen() throws IOException {
        Random random = new Random();

        //不使用buffer
        //FileOutputStream fileOutputStream = new FileOutputStream(filePath);

        //使用buffer
        int bufferSize = 8 * 1024;//linux 分页大小,默认设置的是8k,一般设置成默认值是最佳的状态
        //这个是java中的io版本。不属于nio
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath), bufferSize);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 100000000; i++) {
            for (int j = 0; j < 5; j++) {
                bufferedOutputStream.write(97 + random.nextInt(5));
            }
            bufferedOutputStream.write(' ');
        }

        bufferedOutputStream.close();

        System.out.println("time is " + (System.currentTimeMillis() - startTime));
    }

    //不使用buffer
    @Test
    public void testRead() throws IOException {

        FileInputStream fileInputStream = new FileInputStream(filePath);

        long startTime = System.currentTimeMillis();

        int b;

        while ((b = fileInputStream.read()) != -1) {
        }

        System.out.println("time is " + (System.currentTimeMillis() - startTime));

        fileInputStream.close();
    }

    //使用ioBuffer
    @Test
    public void testBufferRead() throws IOException {


        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));

        long startTime = System.currentTimeMillis();

        int b;

        while ((b = bufferedInputStream.read()) != -1) {
        }

        System.out.println("time is " + (System.currentTimeMillis() - startTime));
    }

    //使用nioBuffer
    @Test
    public void testBufferNio() throws IOException {
        //linux，一切皆是文件
        FileInputStream fileInputStream = new FileInputStream(filePath);
        FileChannel channel = fileInputStream.getChannel();
        //start Nio
        ByteBuffer byteBuffer = ByteBuffer.allocate(8 * 1024);

        long startTime = System.currentTimeMillis();

        while (channel.read(byteBuffer) != -1) {
            byteBuffer.flip();
            byteBuffer.clear();
        }

        System.out.println("time is " + (System.currentTimeMillis() - startTime));

    }

    //使用异步
    @Test
    public void testAsyncRead() throws IOException, ExecutionException, InterruptedException {
        //java file io


        //第一个参数值为必传，第二个参数为选传
        Path path = Paths.get(filePath);


        AsynchronousFileChannel open = AsynchronousFileChannel.open(path, StandardOpenOption.READ);

        ByteBuffer byteBuffer = ByteBuffer.allocate(8 * 1024);

        Future<Integer> read = open.read(byteBuffer, 0);
        Integer numRead = read.get();
        byteBuffer.flip();

        String s = new String(byteBuffer.array());
        byteBuffer.clear();
        System.out.println("end");

    }


    @Test
    public void testChinese() {
        String chinese = "长坂桥头杀气生，横枪立马眼圆睁。一声好似轰雷震，独退曹家百万兵。";

        Charset utf8 = StandardCharsets.UTF_8;

        byte[] bytes = utf8.encode(chinese).array();

        byte[] bytes2 = Arrays.copyOfRange(bytes, 0, 11);

        ByteBuffer bBuf = ByteBuffer.allocate(12);
        CharBuffer cBuf = CharBuffer.allocate(12);

        bBuf.put(bytes2);
        //read byteBuffer，线程处理只会的第一次读取
        bBuf.flip();
        System.out.println("bBuf is " + bBuf);

        //charset的decode,byteBuffer change charBuffer,超出给定的大小，可进行扩容
        utf8.newDecoder().decode(bBuf, cBuf, true);

        //read charBuffer,线程处理只会的第一次读取
        cBuf.flip();
        System.out.println("cBuf is " + cBuf);

        char[] chars = new char[cBuf.length()];
        if (cBuf.hasRemaining()) {
            //从0开始读取，线程处理之后的第二次读取，读取到真正的值到控制台
            cBuf.get(chars);
            System.out.println("here:" + Arrays.toString(chars));
        }

        System.out.format("limit-pos=%d\n", bBuf.limit() - bBuf.position());

        //如果想知道buffer还能不能读取
        if ((bBuf.limit() - bBuf.position()) > 0) {
            byte[] bytes1 = Arrays.copyOfRange(bBuf.array(), bBuf.position(), bBuf.limit());
            //方式依旧，如果还需要读取字符的话
        }
    }


}
